using System.Web.Mvc;
using gnodotnet.Core.MailingList;
using SharpArch.Core.PersistenceSupport;
using SharpArch.Core.DomainModel;
using System.Collections.Generic;
using System;
using SharpArch.Web.NHibernate;
using NHibernate.Validator.Engine;
using System.Text;
using SharpArch.Web.CommonValidator;
using SharpArch.Core;

namespace gnodotnet.Web.Controllers.MailingList
{
    [HandleError]
    public class MessagesController : Controller
    {
        public MessagesController(IRepository<Message> messageRepository, IMessanger messanger) {
            Check.Require(messageRepository != null, "messageRepository may not be null");
            Check.Require(!messanger.IsNull(), "Messanger may not be null");

            _messageRepository = messageRepository;
            _messanger = messanger;
        }

        [Transaction]
        public ActionResult Index() {
            IList<Message> messages = _messageRepository.GetAll();
            return View(messages);
        }

        [Transaction]
        public ActionResult Show(int id) {
            Message message = _messageRepository.Get(id);
            return View(message);
        }

        public ActionResult Create() {
            MessageFormViewModel viewModel = MessageFormViewModel.CreateMessageFormViewModel();
            return View(viewModel);
        }

        [ValidateAntiForgeryToken]
        [Transaction]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create(Message message) {
            if (ViewData.ModelState.IsValid && message.IsValid()) {
                _messageRepository.SaveOrUpdate(message);

                TempData[ControllerEnums.GlobalViewDataProperty.PageMessage.ToString()] = 
					"The message was successfully created.";
                return RedirectToAction("Index");
            }

            MessageFormViewModel viewModel = MessageFormViewModel.CreateMessageFormViewModel();
            viewModel.Message = message;
            return View(viewModel);
        }

        [Transaction]
        public ActionResult Edit(int id) {
            MessageFormViewModel viewModel = MessageFormViewModel.CreateMessageFormViewModel();
            viewModel.Message = _messageRepository.Get(id);
            return View(viewModel);
        }

        [ValidateAntiForgeryToken]
        [Transaction]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(Message message) {
            Message messageToUpdate = _messageRepository.Get(message.Id);
            TransferFormValuesTo(messageToUpdate, message);

            if (ViewData.ModelState.IsValid && message.IsValid()) {
                TempData[ControllerEnums.GlobalViewDataProperty.PageMessage.ToString()] = 
					"The message was successfully updated.";
                return RedirectToAction("Index");
            }
            else {
                _messageRepository.DbContext.RollbackTransaction();

				MessageFormViewModel viewModel = MessageFormViewModel.CreateMessageFormViewModel();
				viewModel.Message = message;
				return View(viewModel);
            }
        }

        private void TransferFormValuesTo(Message messageToUpdate, Message messageFromForm) {
			messageToUpdate.Subject = messageFromForm.Subject;
			messageToUpdate.Contents = messageFromForm.Contents;
        }

        [ValidateAntiForgeryToken]
        [Transaction]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete(int id) {
            string resultMessage = "The message was successfully deleted.";
            Message messageToDelete = _messageRepository.Get(id);

            if (messageToDelete != null) {
                _messageRepository.Delete(messageToDelete);

                try {
                    _messageRepository.DbContext.CommitChanges();
                }
                catch {
                    resultMessage = "A problem was encountered preventing the message from being deleted. " +
						"Another item likely depends on this message.";
                    _messageRepository.DbContext.RollbackTransaction();
                }
            }
            else {
                resultMessage = "The message could not be found for deletion. It may already have been deleted.";
            }

            TempData[ControllerEnums.GlobalViewDataProperty.PageMessage.ToString()] = resultMessage;
            return RedirectToAction("Index");
        }

		/// <summary>
		/// Holds data to be passed to the Message form for creates and edits
		/// </summary>
        public class MessageFormViewModel
        {
            private MessageFormViewModel() {}

			/// <summary>
			/// Creation method for creating the view model. Services may be passed to the creation 
			/// method to instantiate items such as lists for drop down boxes.
			/// </summary>
            public static MessageFormViewModel CreateMessageFormViewModel() {
                MessageFormViewModel viewModel = new MessageFormViewModel();
                
                return viewModel;
            }

            public Message Message { get; internal set; }
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Send(int id) {
            Message message = null;
            try {
                message = _messageRepository.Get(id);
                if (message.IsNull())
                    throw new Exception("Message Id {0} was not found".Use(id));
                message.Send(DateTime.Now, _messanger);
                TempData[ControllerEnums.GlobalViewDataProperty.PageMessage.ToString()] =
                    "The message was sent.";
                return RedirectToAction("Index");
            }
            catch (Exception e) {
                MessageFormViewModel viewModel = MessageFormViewModel.CreateMessageFormViewModel();
				viewModel.Message = message;
                TempData[ControllerEnums.GlobalViewDataProperty.ErrorDescription.ToString()] = e.Message;
                return View(viewModel);
            }
        }
        private IMessanger _messanger;
        private readonly IRepository<Message> _messageRepository;
    }
}
